home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Add-On
/
Workbench Add-On - Volume 1.iso
/
DiskUtil
/
Misc
/
BTNTape
/
src
/
btnio.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-03
|
7KB
|
277 lines
/*
** TapeIO: performs operations to the tape unit via SCSI-direct for BTNtape
** Version 3.0 03/14/94
**
** (c) Copyright 1990, 1994 Robert Rethemeyer.
** This code is freely distributable and redistributable,
** for non-commercial purposes, provided this notice is included.
**
** This code was derived from programs written by Robert Mitchell.
*/
#define _STRICT_ANSI
#include <exec/types.h>
#include <exec/io.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <devices/scsidisk.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "btn.h"
#include "tplink.h"
#include <proto/exec.h>
#include <pragmas/exec_pragmas.h>
#define DBUG 0
/* SCSI commands used by handler */
#define CMD_TEST_UNIT_READY 0x00
#define CMD_REWIND 0x01
#define CMD_REQUEST_SENSE 0x03
#define CMD_SCSI_READ 0x08
#define CMD_SCSI_WRITE 0x0a
#define CMD_FILEMARK 0x10
#define CMD_SPACE 0x11
#define CMD_INQUIRY 0x12
#define CMD_MODE_SELECT 0x15
#define CMD_MODE_SENSE 0x1a
#define CMD_LOAD_UNLOAD 0x1b
#define CMD_READ_CAPACITY 0x25
extern UBYTE *cdb;
extern UBYTE *sns;
extern UBYTE *inq;
extern struct SCSICmd *cmd;
extern UBYTE *TapeBuff[2];
extern struct IOStdReq *ior;
extern ULONG blknum;
extern ULONG blksize;
extern ULONG numblks;
extern ULONG TBSize;
extern ULONG rwlen;
extern ULONG rdlen;
extern ULONG expect;
extern ULONG bugmask;
extern long filenum;
extern long lastwrtn;
extern long actual;
extern long Boff;
extern long reserved;
extern long tpsize;
extern struct tplink *linktp;
extern BOOL inprog;
extern BOOL bswap;
extern BOOL dbug;
extern char dbb[80];
extern UBYTE Lun;
extern UBYTE varblk;
extern UBYTE fixedbit;
long TapeIO(int toper, long bn, int ctl)
{
char *z; int i; ULONG bc;
if(inprog) {
WaitIO((struct IORequest *)ior);
inprog = FALSE;
if(actual<0) actual = cmd->scsi_Actual;
if(cdb[0]==CMD_SCSI_READ) Mprintf("%ld bytes\n",actual);
if(ior->io_Error) return((long)(ior->io_Error));
}
if(toper == TFINISH) return(0L);
cmd->scsi_Command = cdb;
cmd->scsi_CmdLength = 6;
cmd->scsi_Status = 0;
cmd->scsi_Length = 0;
cmd->scsi_Actual = 0;
cmd->scsi_Flags = 0;
ior->io_Command = HD_SCSICMD;
ior->io_Data = (APTR) cmd;
ior->io_Length = sizeof(struct SCSICmd);
ior->io_Error = 0;
for (i=0 ; i<10; i++) cdb[i] = 0x00;
switch(toper) {
case TWRITE:
if(varblk) bc = expect = cmd->scsi_Length = Boff;
else {
bc = ((Boff-1)/blksize)+1;
cmd->scsi_Length = expect = bc * blksize;
}
if(DAC) if((blknum+bc)>tpsize) return(FAKEOM);
if(bswap) swapbytes(TapeBuff[bn]);
cdb[0] = CMD_SCSI_WRITE;
cdb[1] = Lun | fixedbit;
*((UWORD *)&cdb[2]) = (SEQ) ? (UWORD)(bc>>8) : (UWORD) blknum;
cdb[4] = (UBYTE) bc & 0xff;
/* cmd->scsi_Data = (UWORD *) TapeBuff[bn]; */ /* 2090A bug fix */
cmd->scsi_Data = (UWORD *) ((ULONG) TapeBuff[bn] | bugmask);
cmd->scsi_Flags = SCSIF_WRITE;
actual = bc;
Mprintf("Writing block %lu: %lu bytes\n",blknum,expect);
break;
case TREAD:
if(DAC) if((blknum+numblks)>tpsize) return(FAKEOM);
cdb[0] = CMD_SCSI_READ;
cdb[1] = Lun | fixedbit;
*((UWORD *)&cdb[2]) = (SEQ) ? (UWORD)(rdlen>>8) : (UWORD) blknum;
cdb[4] = (UBYTE) rdlen & 0xff;
cmd->scsi_Data = (UWORD *) TapeBuff[bn];
cmd->scsi_Length = expect = rwlen;
cmd->scsi_Flags = SCSIF_READ;
actual = -1;
Mprintf("Reading block %lu:",blknum);
break;
case TSENSE:
for (i=0 ; i<32; i++) sns[i] = 0;
cdb[0] = CMD_REQUEST_SENSE;
cdb[1] = Lun;
cdb[4] = 32; /* extended sense */
cmd->scsi_Length = 32;
cmd->scsi_Data = (UWORD *) sns;
cmd->scsi_Flags = SCSIF_READ;
break;
case TREWIND:
cdb[0] = CMD_REWIND;
cdb[1] = Lun;
filenum = reserved;
lastwrtn = -1;
Mprintf("Rewinding\n");
break;
case INQUIRY: /* read drive information */
cdb[0] = CMD_INQUIRY;
cdb[1] = Lun;
cdb[4] = 36;
cmd->scsi_Length = 36;
cmd->scsi_Data = (UWORD *) inq;
cmd->scsi_Flags = SCSIF_READ;
break;
case TREADY: /* test unit ready */
cdb[0] = CMD_TEST_UNIT_READY;
cdb[1] = Lun;
break;
case MDSNS:
for (i=0 ; i<12; i++) sns[i] = 0;
cdb[0] = CMD_MODE_SENSE;
cdb[1] = Lun;
cdb[4] = 12;
cmd->scsi_Length = 12;
cmd->scsi_Data = (UWORD *) sns;
cmd->scsi_Flags = SCSIF_READ;
break;
case WFMARK: /* write file mark */
cdb[0] = CMD_FILEMARK;
cdb[1] = Lun;
cdb[4] = (UBYTE) bn;
if(bn) Mprintf("Writing filemark\n");
break;
case TSKIPF: /* skip over filemarks */
cdb[0] = CMD_SPACE;
cdb[1] = Lun | 0x01;
cdb[2] = (UBYTE) (bn >> 16);
cdb[3] = (UBYTE) (bn >> 8);
cdb[4] = (UBYTE) bn;
break;
case TSKIPE: /* skip to end-of-data */
cdb[0] = CMD_SPACE;
cdb[1] = Lun | 0x03;
Mprintf("Skipping to end of data\n");
break;
case TRETEN: /* retension tape */
cdb[0] = CMD_LOAD_UNLOAD;
cdb[1] = Lun;
cdb[4] = 0x03;
Mprintf("Retensioning\n");
break;
case TEJECT: /* eject tape */
cdb[0] = CMD_LOAD_UNLOAD;
cdb[1] = Lun;
cdb[4] = 0x00;
Mprintf("Ejecting tape\n");
break;
case RDCAP: /* read tape capacity. 3M drive only */
cdb[0] = CMD_READ_CAPACITY;
cdb[1] = Lun;
cmd->scsi_CmdLength = 10;
cmd->scsi_Length = 8;
cmd->scsi_Data = (UWORD *) sns;
cmd->scsi_Flags = SCSIF_READ;
break;
case RAWCMD: /* write user-provided control command */
i = 0;
z = (char *)TapeBuff[bn];
while(*z!='\n' && i<10) cdb[i++] = (UBYTE) strtoul(z,&z,16);
cdb[1] |= Lun;
if(cdb[0] == CMD_REWIND) { blknum = filenum = reserved; lastwrtn = -1; }
if(cdb[0] >= 0x20) cmd->scsi_CmdLength = 10;
if(cdb[0] >= 0xa0) cmd->scsi_CmdLength = 12;
cmd->scsi_Data = (UWORD *) sns;
Mprintf("Raw command %02X\n",cdb[0]);
break;
case MDSET: /* set fixed-mode block length */
cdb[0] = CMD_MODE_SELECT;
cdb[1] = Lun;
cdb[4] = 12;
for (i=0 ; i<12; i++) sns[i] = 0x00;
sns[2] = 0x10; /* buffered mode */
sns[3] = 8;
if(!bn) *((ULONG *)&sns[8]) = blksize & 0x00ffffff; /* block length */
cmd->scsi_Length = 12;
cmd->scsi_Data = (UWORD *) sns;
cmd->scsi_Flags = SCSIF_WRITE;
Mprintf("Mode Select, new block size %lu\n",blksize);
break;
case USRMODE: /* write user-provided mode-select data */
for (i=0 ; i<64; i++) sns[i] = 0x00;
i = 0;
z = (char *)TapeBuff[bn];
while(*z!='\n' && i<64) sns[i++] = (UBYTE) strtoul(z,&z,16);
cdb[0] = CMD_MODE_SELECT;
cdb[1] = Lun;
cdb[4] = i;
cmd->scsi_Length = i;
cmd->scsi_Data = (UWORD *) sns;
cmd->scsi_Flags = SCSIF_WRITE;
Mprintf("User Mode-Select\n");
break;
}
#ifdef DBUG
if(dbug) Mprintf("CDB= %02X %02X %02X %02X %02X %02X ADR=%08X LEN=%X\n",
cdb[0],cdb[1],cdb[2],cdb[3],cdb[4],cdb[5],
cmd->scsi_Data, cmd->scsi_Length);
#endif
if(ctl == CTLWAIT) {
DoIO ((struct IORequest *)ior); /* start sync io */
if(actual<0) actual = cmd->scsi_Actual;
if(cdb[0]==CMD_SCSI_READ) Mprintf("%ld bytes\n",actual);
return((long)(ior->io_Error));
}
else {
SendIO((struct IORequest *)ior); /* start async io */
inprog = TRUE;
return(0L);
}
}